/*
 * mpu6050.c
 *
 *  Created on: May 21, 2021
 *      Author: kirk_
 */

#include "mpu6050.h"
#include "cmsis_os.h"

uint8_t MPU6050_Init(MPU6050_t *kmpu, I2C_HandleTypeDef* hi2c, uint16_t addr)
{
	uint8_t res;

	if(kmpu == NULL)
		return KDL_ERROR;
	if(hi2c == NULL)
		return KDL_ERROR;
	if(!IS_I2C_ALL_INSTANCE(hi2c->Instance))
		return KDL_ERROR;

	/* Pass parameter */
	kmpu->hi2c = hi2c;
	kmpu->i2c = hi2c->Instance;
	kmpu->address = addr;

	/* Initialize */
	MPU6050_Write_Byte(kmpu, MPU6050_PWR_MGMT1_REG,0X80);	//复位MPU6050
	osDelay(1);
	MPU6050_Write_Byte(kmpu, MPU6050_PWR_MGMT1_REG,0X00);	//唤醒MPU6050
	osDelay(1);
	MPU6050_Set_Gyro_Fsr(kmpu, 3);					//陀螺仪传感器,±2000dps
	osDelay(1);
	MPU6050_Set_Accel_Fsr(kmpu, 0);					//加速度传感器,±2g
	osDelay(1);
	MPU6050_Write_Byte(kmpu, MPU6050_INT_EN_REG,0X00);	//关闭所有中断
	osDelay(1);
	MPU6050_Write_Byte(kmpu, MPU6050_USER_CTRL_REG,0X00);	//I2C主模式关闭
	osDelay(1);
	MPU6050_Write_Byte(kmpu, MPU6050_FIFO_EN_REG,0X00);	//关闭FIFO
	osDelay(1);
	MPU6050_Write_Byte(kmpu, MPU6050_INTBP_CFG_REG,0X80);	//INT引脚低电平有效
	osDelay(1);
	res=MPU6050_Read_Byte(kmpu, MPU6050_DEVICE_ID_REG);
	osDelay(1);
	res <<= 1;
	if(res==addr)//器件ID正确
	{
		MPU6050_Write_Byte(kmpu, MPU6050_PWR_MGMT1_REG,0X01);	//设置CLKSEL,PLL X轴为参考
		osDelay(1);
		MPU6050_Write_Byte(kmpu, MPU6050_PWR_MGMT2_REG,0X00);	//加速度与陀螺仪都工作
		osDelay(1);
		MPU6050_Set_Rate(kmpu, 1000);//Set the sampling frequency to 1KHz
		return 1;
	}
	return 0;
}

/* Configuration functions ****************************************************/
void MPU6050_Set_Gyro_Fsr(MPU6050_t *kmpu, uint8_t fsr)
{
	MPU6050_Write_Byte(kmpu, MPU6050_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围
}

void MPU6050_Set_Accel_Fsr(MPU6050_t *kmpu, uint8_t fsr)
{
	MPU6050_Write_Byte(kmpu, MPU6050_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围
}

void MPU6050_Set_LPF(MPU6050_t *kmpu, uint16_t lpf)
{
	uint8_t data=0;
	if(lpf>=188)data=1;
	else if(lpf>=98)data=2;
	else if(lpf>=42)data=3;
	else if(lpf>=20)data=4;
	else if(lpf>=10)data=5;
	else data=6;
	MPU6050_Write_Byte(kmpu, MPU6050_CFG_REG,data);//设置数字低通滤波器
}

void MPU6050_Set_Rate(MPU6050_t *kmpu, uint16_t rate)
{
	uint8_t data;
	if(rate>1000)rate=1000;
	if(rate<4)rate=4;
	data=1000/rate-1;
	MPU6050_Write_Byte(kmpu, MPU6050_SAMPLE_RATE_REG,data);	//设置数字低通滤波器
 	MPU6050_Set_LPF(kmpu, rate/2);	//自动设置LPF为采样率的一半
}

void MPU6050_Set_Fifo(MPU6050_t *kmpu, uint8_t sens)
{

}


/* IO operation functions *****************************************************/
void MPU6050_Get_Temperature(MPU6050_t *kmpu)
{
	  unsigned char  buf[2];
	  short raw;
	  double temp;

	  MPU6050_Read_Len(kmpu, MPU6050_TEMP_OUTH_REG,2,buf);
	  raw = (buf[0]<<8)| buf[1];
	  temp = ((double)36.53+((double)raw)/340)*100;
	  //  temp = (long)((35 + (raw / 340)) * 65536L);
	  kmpu->Temp = temp / 100;
	  ///return temp/100.0f;
}

void MPU6050_Get_Gyroscope(MPU6050_t *kmpu)
{
	int16_t gx, gy, gz;
    uint8_t buf[6],res;
	//res=MPU6050_Read_Len(MPU6050_GYRO_XOUTH_REG,6,buf);
	res = HAL_I2C_Mem_Read(kmpu->hi2c, kmpu->address, MPU6050_GYRO_XOUTH_REG, I2C_MEMADD_SIZE_8BIT, buf, 6, 0xfff);
	if(res==0)
	{
		gx=((uint16_t)buf[0]<<8)|buf[1];
		gy=((uint16_t)buf[2]<<8)|buf[3];
		gz=((uint16_t)buf[4]<<8)|buf[5];
	}

	kmpu->GyrX = (double)gx / MPU6050_GYR_PRECISION;
	kmpu->GyrY = (double)gy / MPU6050_GYR_PRECISION;
	kmpu->GyrZ = (double)gz / MPU6050_GYR_PRECISION;
}

void MPU6050_Get_Accelerometer(MPU6050_t *kmpu)
{
    int16_t ax,ay, az;
    uint8_t buf[6],res;
	//res=MPU6050_Read_Len(MPU6050_ACCEL_XOUTH_REG,6,buf);
	res = HAL_I2C_Mem_Read(kmpu->hi2c, kmpu->address, MPU6050_ACCEL_XOUTH_REG, I2C_MEMADD_SIZE_8BIT, buf, 6, 0xfff);
	if(res==0)
	{
		ax=((uint16_t)buf[0]<<8)|buf[1];
		ay=((uint16_t)buf[2]<<8)|buf[3];
		az=((uint16_t)buf[4]<<8)|buf[5];
	}

	kmpu->AccX = (double)ax / MPU6050_ACC_PRECISION;
	kmpu->AccY = (double)ay / MPU6050_ACC_PRECISION;
	kmpu->AccZ = (double)az / MPU6050_ACC_PRECISION;

	kmpu->AccS = sqrt(kmpu->AccX*kmpu->AccX + kmpu->AccY*kmpu->AccY + kmpu->AccZ*kmpu->AccZ);
}


/* State and Error functions **************************************************/
void MPU6050_Write_Len(MPU6050_t *kmpu, uint8_t reg,uint8_t len,uint8_t *buf)
{
	HAL_I2C_Mem_Write(kmpu->hi2c, kmpu->address+1, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 0xfff);
}

void MPU6050_Read_Len(MPU6050_t *kmpu, uint8_t reg,uint8_t len,uint8_t *buf)
{
	HAL_I2C_Mem_Read(kmpu->hi2c, kmpu->address, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 0xfff);
}

void MPU6050_Write_Byte(MPU6050_t *kmpu, uint8_t reg,uint8_t data)
{
	HAL_I2C_Mem_Write(kmpu->hi2c, kmpu->address+1, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 0xfff);
}

uint8_t MPU6050_Read_Byte(MPU6050_t *kmpu, uint8_t reg)
{
	unsigned char data=0;

	HAL_I2C_Mem_Read(kmpu->hi2c, kmpu->address, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 0xfff);

	return data;
}


